package org.xliu.cs.openproject.codegenerator;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.exception.MethodInvocationException;
import org.apache.velocity.exception.ParseErrorException;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.xliu.cs.openproject.codegenerator.restapi.ApiDescription;

import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Properties;

/**
 * C++ Web客户端代码生成器
 * 根据API描述文件生成C++客户端代码，使用libcurl和nlohmann-json库
 */
public class CppWebClientGenerator {
    private final ObjectMapper objectMapper = new ObjectMapper();
    private static final Template serviceClientTemplate;

    static {
        Properties props = new Properties();
        props.setProperty("resource.loader", "class");
        props.setProperty("class.resource.loader.class",
                "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
        Velocity.init(props);
        
        // 获取模板
        serviceClientTemplate = Velocity.getTemplate("service_client.h.vm");
    }

    /**
     * 根据API描述文件生成C++客户端代码
     * @param apiDescriptionPath API描述文件路径
     * @param outputPath 生成代码的输出目录
     * @throws IOException IO异常
     */
    public void generate(String apiDescriptionPath, String outputPath) throws IOException {
        // 读取API描述文件
        String content = new String(Files.readAllBytes(Paths.get(apiDescriptionPath)));
        JsonNode apiDescriptionNode = objectMapper.readTree(content);
        
        // 将JsonNode转换为专门的类
        ApiDescription apiDescription = ApiDescription.fromJsonNode(apiDescriptionNode, objectMapper);

        // 创建输出目录
        Path outPath = Paths.get(outputPath);
        Files.createDirectories(outPath);

        // 生成特定服务的客户端接口代码
        generateServiceClient(apiDescription, outPath);

        System.out.println("C++客户端代码生成完成: " + outputPath);
    }

    /**
     * 生成特定服务的客户端接口代码
     */
    private void generateServiceClient(ApiDescription apiDescription, Path outputPath) {
        String serviceName = apiDescription.getService().getName();
        
        try {
            // 创建上下文并添加数据模型
            VelocityContext context = new VelocityContext();
            context.put("service", apiDescription.getService());
            context.put("apis", apiDescription.getApis());

            // 获取服务名称并生成文件名
            String fileName = serviceName + "Client.h";
            Path serviceClientHeaderFile = Paths.get(outputPath.toString(), fileName);
            
            // 处理模板并生成输出
            try (BufferedWriter writer = Files.newBufferedWriter(serviceClientHeaderFile)) {
                serviceClientTemplate.merge(context, writer);
            }
        } catch (ResourceNotFoundException e) {
            System.err.println("模板文件未找到: " + e.getMessage());
        } catch (ParseErrorException | MethodInvocationException e) {
            System.err.println("模板处理错误: " + e.getMessage());
        } catch (Exception e) {
            System.err.println("生成C++客户端代码时出错: " + e.getMessage());
            e.printStackTrace();
        }
    }
}